#pragma once
#include <iostream>
#include <mutex>

namespace hanger
{
    /*饿汉式单例模式*/
    class Singleton
    {
    private:
        static Singleton instance;

    private:
        Singleton() // 构造函数私有化
        { 
            std::cout << "Singleton()单例对象已构造\n";
        };
        Singleton(Singleton &sig) = delete;            // C++11防止拷贝
        Singleton &operator=(Singleton &sig) = delete; // C++11防止拷贝
    public:
        inline static Singleton *getInstance()
        {
            return &instance;
        }
        void doSomething()
        {
            // 加锁~
            std::cout << "doSomething()\n";
        }
    };
}

namespace lazy
{
    /*懒汉式单例模式*/
    class Singleton
    {
        struct Deleter
        {
            ~Deleter()
            {
                if (nullptr != Singleton::instance)
                {
                    delete Singleton::instance;
                    std::cout << "单例对象成功释放\n";
                }
            }
        };

    private:
        static Singleton *instance;
        static std::mutex mtx;
        static Deleter deleter; // 定义一个内部类对象，当单例对象析构时，deleter对象也会调用析构函数，从而释放单例对象

    private:
        Singleton() // 构造函数私有化
        { 
            std::cout << "Singleton()单例对象已构造\n";
        };
        Singleton(Singleton &sig) = delete;            // C++11防止拷贝
        Singleton &operator=(Singleton &sig) = delete; // C++11防止拷贝
    public:
        static Singleton *getInstance()
        {
            if (nullptr == instance)
            {
                std::lock_guard<std::mutex> lock(mtx);
                if (nullptr == instance)
                    instance = new Singleton();
            }
            return instance;
        }
    };

    // 类内声明，类外定义
    Singleton *Singleton::instance = nullptr;
    std::mutex Singleton::mtx;
    Singleton::Deleter Singleton::deleter;
}

namespace lazy_elegant
{
    class Singleton
    {
    private:
        static Singleton instance;
    private:
        Singleton() // 构造函数私有化
        { 
            std::cout << "Singleton()单例对象已构造\n";
        };
        Singleton(Singleton &sig) = delete;            // C++11防止拷贝
        Singleton &operator=(Singleton &sig) = delete; // C++11防止拷贝
    public:
        inline static Singleton& getInstance()
        {
            static Singleton ins; //多个线程同时访问，且该静态变量初次构造，则只能有一个线程构造
            return ins;
        }
        void doSomething()
        {
            // 加锁~
            std::cout << "doSomething()\n";
        }
    };
}
